package org.artifact.core.plugin.netty.packet;

import java.nio.ByteBuffer;

import io.netty.buffer.ByteBuf;

public class NettyPacketUtil {
	/**
	 * 默认解密密钥
	 */
	private static final int[] DEFAULT_CUSTOME_DECRYPTION_KEYS = new int[] { 0xac, 0x12, 0x19, 0xcd, 0x95, 0x34, 0xcb,
			0xf1 };
	/**
	 * 默认加密密钥
	 */
	private static final int[] DEFAULT_CUSTOME_ENCRYPTION_KEYS = new int[] { 0xac, 0x12, 0x19, 0xcd, 0x95, 0x34, 0xcb,
			0xf1 };

	/**
	 * 默认解密密钥
	 * 
	 * @return 默认解密密钥
	 */
	public static int[] getDefaultCustomDecryptionKeys() {
		int[] keys = new int[DEFAULT_CUSTOME_DECRYPTION_KEYS.length];
		System.arraycopy(DEFAULT_CUSTOME_DECRYPTION_KEYS, 0, keys, 0, keys.length);
		return keys;
	}

	/**
	 * 默认加密密钥
	 * 
	 * @return 默认加密密钥
	 */
	public static int[] getDefaultCustomEncryptionKeys() {
		int[] keys = new int[DEFAULT_CUSTOME_ENCRYPTION_KEYS.length];
		System.arraycopy(DEFAULT_CUSTOME_ENCRYPTION_KEYS, 0, keys, 0, keys.length);
		return keys;
	}
	
	public static byte[] decrypt(byte[] data, int[] decryptKey) {
		return decrypt(data, decryptKey, 0, data.length);
	}
	
	// 解密
	public static byte[] decrypt(byte[] data, int[] decryptKey, int startIndex, int length) {
		byte lastCipherByte = 0;
		byte oldVal = 0;

		int tmpIndex = 0;
		int keyIndex = 0;
		
		int index = startIndex;
        int endIndex = startIndex+length;
        while (index < endIndex) {
        	tmpIndex = index;
			keyIndex = (index - startIndex) & (decryptKey.length - 1);
			// 历史值
			oldVal = data[tmpIndex];

			decryptKey[keyIndex] = ((decryptKey[keyIndex] + lastCipherByte) ^ (index - startIndex)) & 0xff;
			data[tmpIndex] = (byte) ((((data[index] & 0xff) - lastCipherByte) ^ decryptKey[keyIndex]) & 0xff);
			lastCipherByte = oldVal;
			index++;
        }
        return data;
	}

	public static byte[] encrypt(byte[] data, int[] encryptKey) {
		return decrypt(data, encryptKey, 0, data.length);
	} 
	
	// 加密
	public static byte[] encrypt(byte[] data, int[] encryptKey, int startIndex, int length) {
		int lastCipherByte = 0;

		// 循环加密
		int keyIndex = 0;
		int tempIndex = 0;
		
		int index = startIndex;
        int endIndex = startIndex+length;
        while (index < endIndex) {
        	keyIndex = (index - startIndex) & (encryptKey.length - 1);
			tempIndex = index;
			encryptKey[keyIndex] = ((encryptKey[keyIndex] + lastCipherByte) ^ (index - startIndex)) & 0xff;
			lastCipherByte = (((data[tempIndex] ^ encryptKey[keyIndex]) & 0xff) + lastCipherByte) & 0xff;
			data[tempIndex] = (byte) lastCipherByte;
			index++;
        }
		return data;
	}
	
	
	
	public static ByteBuf decrypt(ByteBuf byteBuf, int[] decryptKey) {
		return decrypt(byteBuf, decryptKey, byteBuf.readerIndex(), byteBuf.readableBytes());
	}
	
	// 解密
	public static ByteBuf decrypt(ByteBuf byteBuf, int[] decryptKey, int startIndex, int length) {
		byte lastCipherByte = 0;
		byte oldVal = 0;

		int tmpIndex = 0;
		int keyIndex = 0;
		
		int index = startIndex;
        int endIndex = startIndex+length;
        while (index < endIndex) {
        	tmpIndex = index;
			keyIndex = (index - startIndex) & (decryptKey.length - 1);
			// 历史值
			oldVal = byteBuf.getByte(tmpIndex);

			decryptKey[keyIndex] = ((decryptKey[keyIndex] + lastCipherByte) ^ (index - startIndex)) & 0xff;
			byte newVal = (byte) ((((byteBuf.getByte(index) & 0xff) - lastCipherByte) ^ decryptKey[keyIndex]) & 0xff);
			byteBuf.setByte(tmpIndex, newVal);
			lastCipherByte = oldVal;
			index++;
        }
        return byteBuf;
	}

	public static ByteBuf encrypt(ByteBuf byteBuf, int[] encryptKey) {
		return decrypt(byteBuf, encryptKey, byteBuf.readerIndex(), byteBuf.readableBytes());
	} 
	
	// 加密
	public static ByteBuf encrypt(ByteBuf byteBuf, int[] encryptKey, int startIndex, int length) {
		int lastCipherByte = 0;

		// 循环加密
		int keyIndex = 0;
		int tempIndex = 0;
		
		int index = startIndex;
        int endIndex = startIndex+length;
        while (index < endIndex) {
        	keyIndex = (index - startIndex) & (encryptKey.length - 1);
			tempIndex = index;
			encryptKey[keyIndex] = ((encryptKey[keyIndex] + lastCipherByte) ^ (index - startIndex)) & 0xff;
			lastCipherByte = (((byteBuf.getByte(tempIndex) ^ encryptKey[keyIndex]) & 0xff) + lastCipherByte) & 0xff;
			byteBuf.setByte(tempIndex, (byte) lastCipherByte);
			index++;
        }
		return byteBuf;
	}
	
	/**
     * 计算校验和
     * @return 校验和
     */
	public static short sumCheck(byte[] data,int startIndex,int length) {
		int val = 0x77;
		int index = startIndex;
        int endIndex = startIndex+length;
        while (index < endIndex)
        {
            val += (data[index++] & 0xFF);
        }
		return (short) (val & 0x7F7F);
	}
	
	/**
     * 计算校验和
     * @return 校验和
     */
    public static short sumCheck(byte[] data)
    {
        return sumCheck(data, 0, data.length);
    }
    
    
    /**
     * 计算校验和
     * @return 校验和
     */
    public static short sumCheck(ByteBuf byteBuf){
    	return sumCheck(byteBuf,byteBuf.readerIndex(),byteBuf.readableBytes());
    }
    
    /**
     * 计算校验和
     * @return 校验和
     */
    public static short sumCheck(ByteBuf byteBuff,int startIndex,int length){
    	int val = 0x77;
		int index = startIndex;
        int endIndex = startIndex+length;
        while (index < endIndex)
        {
            val += (byteBuff.getByte(index++) & 0xFF);
        }
		return (short) (val & 0x7F7F);
    }
}
